/**
  ******************************************************************************
             Copyright(c) 2023 China Core Co. Ltd.
                      All Rights Reserved
  ******************************************************************************
  * @file    ssi_drv.h
  * @author  Product application department
  * @version V1.0
  * @date    2023.10.26
  * @brief   Header file of SSI DRV module.
  *
  ******************************************************************************
  */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __SSI_DRV_H
#define __SSI_DRV_H
#ifdef __cplusplus
extern "C"
{
#endif

/* Includes ------------------------------------------------------------------*/
#include "drv.h"
#include "type.h"
#include "delay.h"
// #include "debug.h"
#include "status.h"
//#include "dma_hal.h"
#include "interrupt.h"
#include "cpm_drv.h"
#ifdef FILE_OUT
/**@defgroup DRV 3 HAL driver
  *
  *@{
  */

/** @defgroup DRV_SPI SPI
  *
  *@{
  */
#endif
/*****************************Macros Definition***********************************/
#ifdef FILE_OUT
/** @defgroup DRV_SPI_Exported_Macros Exported Macros
  *
  * @{
  */
#endif


//w25q128 CMD
#define DUMMY_BYTE				0xa5
#define READ_ID_CMD				0x90  
#define WRITE_EN_CMD			0x06
#define SECT_ERASE_CMD		0x20  //4K
#define BLOCK_ERASE_CMD		0x52  //32K   0XD8 64K
#define BLK_64K_ERASE_CMD	0xD8


#define GET_SAT1_CMD			0x05
#define READ_CMD					0x03
#define PAGE_PROG_CMD			0x02
#define GET_SAT2_CMD			0x35
#define PROG_STA12_CMD    0x01 
#define PROG_STA2_CMD			0x31
#define DUAL_READ_CMD			0x3b
#define QUAD_PROG_CMD			0x32
#define QUAD_READ_CMD			0x6b
#define QPI_READ_CMD			0x0b
#define QPI_ENTER_CMD			0x38
#define QPI_EXIT_CMD			0xFF
#define SET_READ_PARA_CMD	0xc0
#define Reset_EN_CMD	    0x66
#define Reset_CMD	        0x99
/**
  * @}
  */

/*******************Struct and enum definition*******************************/

/**
  *@brief  SPI initializes the struct definition
  *
  */
typedef struct
{
    uint8_t DFS;      /**<SSI数据帧大小      0x00   CTRLR0*/   
    uint8_t FRF;      /**<SSI数据帧格式      0x00   CTRLR0 */  
    uint8_t SCPH;     /**<串行时钟相位       0x00    */
    uint8_t SCPOL;    /**<串行时钟极性       0x00*/
    uint8_t TMOD;     /**<传输模式           0x00*/
    uint8_t SRL;      /**<位移寄存器循环     0x00*/
    uint8_t SSTE;     /**<从设备选择切换使能 0x00*/
    uint8_t CFS;      /**<控制帧大小         0x00*/          				
    uint8_t Format;   /**<SSI通讯格式        0x00
                          *- STD_mode    Standard SPI Format
                          *- DUAL_mode   Dual SPI Format
                          *- QUAD_mode   Quad SPI Format */
    uint16_t NDF;     /**<数据帧数量     0x04     CTRLR1 */  
	
    uint16_t SSI_BaudRatePrescaler;     /**<SSI时钟分频值   0x14     BAUDR*/ 
    uint8_t Transfer_start_FIFO_level;   //TXFTLR<<16
    uint8_t Transmit_FIFO_Threshold;     //TXFTLR
    uint8_t Receive_FIFO_Threshold;		   //RXFTLR
    uint8_t Trans_Type;                  /**<SSI传输类型      0xf4    SPICTRLR0 */					
    uint8_t Address_Length;              /**<SSI地址长度       0xf4    SPICTRLR0 */
    uint8_t Instruction_length;          /**<SSI指令长度         0xf4    SPICTRLR0  
																						*- INST_L0   No Instruction
																						*- INST_L4   4 bit Instruction length
                                            *- INST_L8   8 bit Instruction length
                                            *- INST_L16  6 bit Instruction length */
    uint8_t WAIT_CYCLES;                 /**<等待cycle数         0xf4    SPICTRLR0 */
    uint8_t CLK_STRETCH_EN;              /**<SPI传输扩展使能      0xf4    SPICTRLR0 */  																	 
																				 
} SSI_InitTypeDef;


/**
  *@brief 标志索引.
  */
typedef enum
{
	SSI_FLAG_INDEX_BUSY = 0x01,
	SSI_FLAG_INDEX_TFNF = 0x02,
	SSI_FLAG_INDEX_TFE  = 0x04,
	SSI_FLAG_INDEX_RFNE = 0x08,
	SSI_FLAG_INDEX_RFF  = 0x10,
}SSI_FlagIndexTypeDef;

#define _ssi_en(ssi)       _bit_set(ssi->SSIENR,SSI_EN)   /**<SPI 使能 */
#define _ssi_dis(ssi)      _bit_clr(ssi->SSIENR,SSI_EN)

/**
  * @brief SPI状态
  */
typedef enum
{
  DRV_SSI_OK       = 0x00,
  DRV_SSI_ERROR    = 0x01,
  DRV_SSI_BUSY     = 0x02,
  DRV_SSI_TIMEOUT  = 0x03,
}DRV_SSI_StatusTypeDef;

/**
  * @brief SPI flash读写状态
  */
typedef enum
{
  DRV_SSI_READ   = 0x00,
  DRV_SSI_WRITE  = 0x01,
}DRV_SSI_ReadTypeDef;

#ifdef FILE_OUT
/** @defgroup DRV_SPI_Exported_Types Exported Types
  *
  * @{
  */
#endif
#define DMACR_TDMAE     0x02
#define DMACR_RDMAE     0x01

#define SR_BUSY         0x01
#define SR_TFNF         0x02
#define SR_TFE          0x04
#define SR_RFNE         0x08
#define SR_RFF          0x10
#define SR_TXE          0x20

#define SSI_PAGE_SIZE       (0x100)
#define SSI_SECTOR_SIZE     (0x1000)


/**
  * @brief DFS struct definition
  */
typedef enum
{
	DFS_01_BIT  = 0x00,
	DFS_02_BIT  = 0x01,
	DFS_03_BIT  = 0x02,
	DFS_04_BIT  = 0x03,
	DFS_05_BIT  = 0x04,
	DFS_06_BIT  = 0x05,
	DFS_07_BIT  = 0x06,
	DFS_08_BIT  = 0x07,
	DFS_09_BIT  = 0x08,
	DFS_10_BIT  = 0x09,
	DFS_11_BIT  = 0x0a,
	DFS_12_BIT  = 0x0b,
	DFS_13_BIT  = 0x0c,
	DFS_14_BIT  = 0x0d,
	DFS_15_BIT  = 0x0e,
	DFS_16_BIT  = 0x0f,
	DFS_17_BIT  = 0x10,
	DFS_18_BIT  = 0x11,
	DFS_19_BIT  = 0x12,
	DFS_20_BIT  = 0x13,
	DFS_21_BIT  = 0x14,
	DFS_22_BIT  = 0x15,
	DFS_23_BIT  = 0x16,
	DFS_24_BIT  = 0x17,
	DFS_25_BIT  = 0x18,
	DFS_26_BIT  = 0x19,
	DFS_27_BIT  = 0x1a,
	DFS_28_BIT  = 0x1b,
	DFS_29_BIT  = 0x1c,
	DFS_30_BIT  = 0x1d,
	DFS_31_BIT  = 0x1e,
	DFS_32_BIT  = 0x1f,
}SSI_DFSTypeDef;
/**
  * @brief FRF格式定义
  */
typedef enum
{
	FRF_SPI       = 0x00,
	FRF_SSP       = 0x01,
	FRF_MICROWIRE = 0x02,
}SSI_FRFTypeDef;

/**
  * @brief SCPH格式定义
  */
typedef enum
{
	SCPH_START_BIT  = 0x01,
	SCPH_MIDDLE_BIT = 0x00,
}SSI_SCPHTypeDef;

/**
  * @brief SCPOL格式定义
  */
typedef enum
{
	INACTIVE_LOW  = 0x01,
	INACTIVE_HIGH = 0x00,
}SSI_SCPOLTypeDef;

/**
  * @brief TMOD格式定义
  */
typedef enum
{
	TX_AND_RX   = 0x00,
	TX_ONLY     = 0x01,
	RX_ONLY     = 0x02,
	EEPROM_READ = 0x03,
}SSI_TMODTypeDef;

/**
  * @brief SRL格式定义
  */
typedef enum
{
	NORMAL_MODE   = 0x00,
	TESTING_MODE  = 0x01,
}SSI_SRLTypeDef;

/**
  * @brief SSTE格式定义
  */
typedef enum
{
	TOGGLE_DISABLE = 0x00,
	TOGGLE_EN      = 0x01,
}SSI_SSTETypeDef;

/**
  * @brief CFS格式定义
  */
typedef enum
{
	CFS_01_BIT  = 0x00,
	CFS_02_BIT  = 0x01,
	CFS_03_BIT  = 0x02,
	CFS_04_BIT  = 0x03,
	CFS_05_BIT  = 0x04,
	CFS_06_BIT  = 0x05,
	CFS_07_BIT  = 0x06,
	CFS_08_BIT  = 0x07,
	CFS_09_BIT  = 0x08,
	CFS_10_BIT  = 0x09,
	CFS_11_BIT  = 0x0a,
	CFS_12_BIT  = 0x0b,
	CFS_13_BIT  = 0x0c,
	CFS_14_BIT  = 0x0d,
	CFS_15_BIT  = 0x0e,
	CFS_16_BIT  = 0x0f,
}SSI_CFSTypeDef;

/**
  * @brief SSI格式定义
  */
typedef enum
{
	STD_mode   = 0x00,
	DUAL_mode  = 0x01,
	QUAD_mode  = 0x02,
}SSI_FormatTypeDef;

/**
  * @brief SSI格式定义
  */
typedef enum
{
	TT0 = 0x00,
	TT1 = 0x01,
	TT2 = 0x02,
	TT3	= 0x03,
}SSI_TransTypeTypeDef;

/**
  * @brief SSI格式定义
  */
typedef enum
{
	ADDR_L0   = 0x00,
	ADDR_L4   = 0x01,
	ADDR_L8   = 0x02,
	ADDR_L12	= 0x03,
	ADDR_L16  = 0x04,
	ADDR_L20  = 0x05,
	ADDR_L24  = 0x06,
	ADDR_L28  = 0x07,
	ADDR_L32  = 0x08,
	ADDR_L36  = 0x09,
	ADDR_L40  = 0x0a,
	ADDR_L44  = 0x0b,
	ADDR_L48  = 0x0c,
	ADDR_L52  = 0x0d,
	ADDR_L56  = 0x0e,
	ADDR_L60  = 0x0f,
}SSI_AdressTypeDef;

/**
  * @brief SSI格式定义
  */
typedef enum
{
	INST_L0  = 0x00,
	INST_L4  = 0x01,
	INST_L8  = 0x02,
	INST_L16 = 0x03,
}SSI_InstructionTypeDef;

/**
  * @brief CLK_STRETCH_EN
  */
typedef enum
{
	CLK_STRETCH_DISABLE = 0x00,
	CLK_STRETCH_ENABLE  = 0x01,
}SSI_CLK_STRETCH_ENTypeDef;

typedef	struct __attribute__((packed,aligned(4)))
{
	volatile unsigned char rsten;		//enable reset
	volatile unsigned char rst;			//reset device
	volatile unsigned char qpien;		//enter qpi mode
	volatile unsigned char setpara;		//set read parameters
	volatile unsigned char readcmd;		//fast read quad i/o
	volatile unsigned char wrapcmd;		//burst read with wrap

	
	volatile unsigned char statrd1;		//read status register-1
	volatile unsigned char statrd2;		//read status register-2
	volatile unsigned char statwr1;		//write status register-1
	volatile unsigned char statwr2;		//write status register-2

	volatile unsigned char quadprog;	//quad input page program
	volatile unsigned char secteras;	//sector erase(4KB)
	volatile unsigned char blkeras32;	//block erase(32KB)
	volatile unsigned char blkeras64;	//block erase(64KB)

	volatile unsigned char writeen;		//write enable
	volatile unsigned char qpi_supported;//support qpi mode
	volatile unsigned char wrapcmd_supported;//support burst read with wrap cmd(wrap with single cmd)	
	volatile unsigned char ssi_status;//status for ssi controller & qspi-flash.0:uninit;1:cmd state;2:xip state.
	
	volatile unsigned char rx_sample_delay;
	
}qspi_cmd_t;

typedef struct
{
	uint8_t  SsiId;           	/*!< SSI read ID*/      
	uint8_t  SysDiv;						/*!< SSI system division*/
	uint8_t  IsQpiMode;    			/*!< SSI QPI mode setting*/  
	uint8_t  IsDualMode;     		/*!< SSI Dual mode setting*/  
	uint16_t StandBaudr;        /*!< SSI stand baud rate setting*/     
	uint16_t QuadBaudr;         /*!< SSI quad baud rate setting*/         
	uint32_t RxSampleDelay;     /*!< SSI receive sample delay time setting*/     
	uint32_t Value;             /*!< SSI transmit data*/        
	uint8_t  Cmd;               /*!< SSI send command*/ 
	uint8_t  IsFourAddr;        /*!< SSI 4-line address setting*/  
	uint8_t  DummyValue;        /*!< SSI dummy data*/ 
	uint8_t  IsMaskInterrupt;   /*!< SSI mask interrupt setting*/ 
//------------------------------------	
	uint8_t   ProgramMode;      /*!< SSI program mode*/ 
	uint16_t  Len;              /*!< SSI transmit data length*/ 
	uint32_t  Addr;             /*!< SSI transmit data address*/ 
	uint32_t  Buf;              /*!< SSI transmit data buffer*/ 
//--------------------------------		
	uint32_t  Delay;            /*!< SSI transmit delay setting*/ 
	uint32_t  Timeout;          /*!< SSI transmit timeout*/ 
	qspi_cmd_t ssi_cmd_t;		    /*!< SSI qspi mode transmit command*/ 
}SSI_ParaTypeDef;

typedef struct
{
	uint8_t (*xip_sys_clk_switch)(SSI_ParaTypeDef *p_ssi_para);

	void (*ssi_open_xip)(SSI_ParaTypeDef *p_ssi_para);
	void (*ssi_close_xip)(SSI_ParaTypeDef *p_ssi_para);

	uint8_t (*xip_enter_qpi)(SSI_ParaTypeDef *p_ssi_para);
	uint8_t (*xip_exit_qpi)(SSI_ParaTypeDef *p_ssi_para);
	uint8_t (*ssi_flash_erase)(SSI_ParaTypeDef *p_ssi_para);
	uint8_t (*ssi_flash_program)(SSI_ParaTypeDef *p_ssi_para);
	uint8_t (*xip_flash_erase)(SSI_ParaTypeDef *p_ssi_para);
	uint8_t (*xip_flash_program)(SSI_ParaTypeDef *p_ssi_para);
}ssi_ops_func_t;


#define 	QUAD_PROGRAM           (0x04)
#define 	QUAD_DMA_PROGRAM       (0x40)
#define 	QUAD_DMA_CH0_PROGRAM   (0x40)
#define 	QUAD_DMA_CH1_PROGRAM   (0x41)
#define 	QUAD_DMA_CH2_PROGRAM   (0x42)
#define 	QUAD_DMA_CH3_PROGRAM   (0x43)
#define 	STD_PROGRAM            (0x01)
#define 	STD_DMA_PROGRAM       (0x10)
#define 	STD_DMA_CH0_PROGRAM   (0x10)
#define 	STD_DMA_CH1_PROGRAM   (0x11)
#define 	STD_DMA_CH2_PROGRAM   (0x12)
#define 	STD_DMA_CH3_PROGRAM   (0x13)

#define 	QPI_PROGRAM           (0x08)
#define 	QPI_DMA_PROGRAM       (0x80)
#define 	QPI_DMA_CH0_PROGRAM   (0x80)
#define 	QPI_DMA_CH1_PROGRAM   (0x81)
#define 	QPI_DMA_CH2_PROGRAM   (0x82)
#define 	QPI_DMA_CH3_PROGRAM   (0x83)

#define ssi_timeout 0xffffff

typedef enum
{
	CMD_READ = 0,
	CMD_WRITE,
	DATA_READ,
	DATA_WRITE,
}QPI_OPT_MODE;

typedef enum
{
	WIDTH_B = 0,
	WIDTH_W,
}SSI_PSRAM_DMA_TRAN;

#define READ_ID						0x9f
#define MR_READ						0xB5
#define WRITE							0x02
#define READ							0x03
#define ENTER_QPI_MODE    0x35
#define EXIT_QPI_MODE			0xF5
#define QPI_WRITE					0x38
#define QPI_FAST_READ     0xEB
#define WRAPPED_READ			0x8B
#define WRAPPED_WRITE			0x82

extern void DRV_SSI_Init(void);
extern void DRV_XIP_SYSCLKSwitch(uint8_t sys_clk_div, uint16_t ssi_clk_div, uint32_t ssi_rx_sample_delay);
extern uint32_t DRV_SSI_GetXIPState(uint32_t addr);
extern void DRV_SSI_OpenXIP(SSI_TypeDef *p_ssi, uint16_t ssi_clk_div, uint32_t ssi_rx_sample_delay, uint8_t qpi_en, uint8_t read_para);
extern void DRV_SSI_CloseXIP(SSI_TypeDef *p_ssi);
extern void DRV_XIP_EnterQPI(SSI_TypeDef *p_ssi, uint8_t read_para);
extern void DRV_XIP_ExitQPI(SSI_TypeDef *p_ssi);
extern void DRV_SSI_FlashProgram(uint32_t addr, uint8_t *p_buff, uint32_t len);
extern uint8_t DRV_XIP_FlashErase(uint32_t addr);
extern uint8_t DRV_XIP_FlashProgram(uint32_t addr, uint8_t *p_buff, uint32_t len);
extern void DRV_XIP_FlashRead(uint32_t addr, uint8_t *p_buff, uint32_t len);
extern void DRV_SSI_StructInit(SSI_InitTypeDef *pinit);
extern DRV_SSI_StatusTypeDef DRV_SSI_WaitonFlagTimeout(SSI_TypeDef *pssi, SSI_FlagIndexTypeDef index, FlagStatusTypeDef status, uint32_t timeout);
extern uint32_t DRV_SSI_GetSsiId(uint32_t addr);
extern DRV_SSI_StatusTypeDef DRV_SSI_clear_fifo(SSI_TypeDef *pssi,uint8_t *status,uint32_t timeout);
extern DRV_SSI_StatusTypeDef DRV_SSI_GetFlag(SSI_TypeDef *pssi,SSI_FlagIndexTypeDef FlagIndex,FlagStatusTypeDef *pflag);

extern void DRV_SSI_Flash_Erase_Block(uint32_t addr);
extern void DRV_XIP_Flash_Erase(uint32_t addr);
extern void DRV_XIP_Flash_Erase_Block(uint32_t addr);
#endif /* __SSI_DRV_H */


